package org.gd.redis.local;

import java.util.*;

public class LocalRedisContainer {

    private Map<String, Map<String, String>> container;
    private Map<String, Map<String, Date>> expire;
    private Map<String, Map<String, Integer>> increments;

    public LocalRedisContainer() {
        container = new HashMap<String, Map<String, String>>();
        expire = new HashMap<String, Map<String, Date>>();
        increments = new HashMap<String, Map<String, Integer>>();
    }

    public void set(String session, String key, String value) {
        set(session, key, value, null);
    }

    public void set(String session, String key, String value, Integer expireSec) {
        if(!container.containsKey(session)) {
            container.put(session, new HashMap<String, String>());
        }
        if(!expire.containsKey(session)) {
            expire.put(session, new HashMap<String, Date>());
        }
        if(!increments.containsKey(session)) {
            increments.put(session, new HashMap<String, Integer>());
        }
        container.get(session).put(key, value);
        if(expire.get(session).containsKey(key)) {
            expire.get(session).remove(key);
        }
        if(increments.get(session).containsKey(key)) {
            increments.get(session).remove(key);
        }
        if(expireSec != null && expireSec > 0) {
            Calendar calendar = new GregorianCalendar();
            calendar.add(Calendar.SECOND, expireSec);
            expire.get(session).put(key, calendar.getTime());
            increments.get(session).put(key, expireSec);
        }
    }

    public String get(String session, String key) {
        if(!container.containsKey(session)) {
            container.put(session, new HashMap<String, String>());
            return null;
        }
        if(!expire.containsKey(session)) {
            expire.put(session, new HashMap<String, Date>());
            return container.get(session).get(key);
        }
        if(!expire.get(session).containsKey(key) || expire.get(session).get(key) == null) {
            return container.get(session).get(key);
        }
        Date date = expire.get(session).get(key);
        if(date.after(new Date())) {
            return container.get(session).get(key);
        } else {
            container.get(session).remove(key);
            expire.get(session).remove(key);
            return null;
        }
    }

    public String iGet(String session, String key) {
        if(!container.containsKey(session)) {
            container.put(session, new HashMap<String, String>());
            return null;
        }
        if(!expire.containsKey(session)) {
            expire.put(session, new HashMap<String, Date>());
            return container.get(session).get(key);
        }
        if(!expire.get(session).containsKey(key) || expire.get(session).get(key) == null) {
            return container.get(session).get(key);
        }
        Date date = expire.get(session).get(key);
        if(date.after(new Date())) {
            expire.get(session).remove(key);
            Integer expireSec = increments.get(session).get(key);
            Calendar calendar = new GregorianCalendar();
            calendar.add(Calendar.SECOND, expireSec);
            expire.get(session).put(key, calendar.getTime());
            return container.get(session).get(key);
        } else {
            container.get(session).remove(key);
            expire.get(session).remove(key);
            increments.get(session).remove(key);
            return null;
        }
    }

    public Map<String, String> getAll(String session) {
        if(!container.containsKey(session)) {
            container.put(session, new HashMap<String, String>());
        } else {
            clearAll(session);
        }
        return container.get(session);
    }

    public Map<String, String> iGetAll(String session) {
        incrementAll(session);
        return getAll(session);
    }

    public void incrementAll(String session) {
        for(Map.Entry<String, Integer> keys: increments.get(session).entrySet()) {
            String key = keys.getKey();
            expire.get(session).remove(key);
            Calendar calendar = new GregorianCalendar();
            calendar.add(Calendar.SECOND, keys.getValue());
            expire.get(session).put(key, calendar.getTime());
        }
    }

    public int hincrBy(String session, String key, int increment) {
        String k1 = LocalRedis.get(session, key);
        if(k1 == null || !k1.matches("\\d{1,12}")) {
            set(session, key, "0");
        }
        Integer count = Integer.parseInt(LocalRedis.get(session, key)) + increment;
        set(session, key, Integer.toString(count));
        return count;
    }

    public void clearAll(String session) {
        if(expire.get(session).isEmpty()) {
            return;
        }
        for(Map.Entry<String, String> keys: container.get(session).entrySet()) {
            String key = keys.getKey();
            if(expire.get(session).containsKey(key)) {
                Date date = expire.get(session).get(key);
                if(date.before(new Date())) {
                    container.get(session).remove(key);
                }
            }
        }
    }

    public boolean isExists(String session) {
        return !(container.get(session) == null || isEmpty(session));
    }

    public boolean isEmpty(String session) {
        return container.get(session).isEmpty();
    }

    public void del(String session) {
        container.remove(session);
        expire.remove(session);
        increments.remove(session);
    }
}
